; Copyright 2013 padnest@gmail.com

; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
;   http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.

; -------------------------------------------------------------------------------
; Extension language for pic18f family
; -------------------------------------------------------------------------------
; Please send any feedback to padnest@gmail.com
; For any update news follow/subscribe to padnest.blogspot.com
; -------------------------------------------------------------------------------
; changelog
; 1.1   added: andlf, cmplf, iorlf, xorlf
; 1.2   added: dec16f, inc16f
; 1.3	added: mov16lf, mov24lf
; 		changed: dec16f, inc16f -> changed params order
; 1.4	headers revision
;		added: callf, callw
;		cleared some compiling warings
; -------------------------------------------------------------------------------


; -------------------------------------------------------------------------------
; Syntax:		andlf lit, freg, dest
; -------------------------------------------------------------------------------
; Description:	Performs AND between a literal value and a file register.
; 				Stores result in W or in a file register.
; Arguments:	lit		the literal value
;				freg	the file register
;				dest	F to store in freg, W to store in WREG
; Affected:		W, STATUS
; Cycles:		2
; -------------------------------------------------------------------------------
andlf macro lit, freg, dest
    movlw   lit
    andwf   freg, dest
    endm

; -------------------------------------------------------------------------------
; Syntax:		callw addr, lit
; -------------------------------------------------------------------------------
; Description:	Loads a literal value into W register and call the subroutine at addr.
; Arguments:	addr	the address of the soubroutine to call
;				lit		the literal value to load in W
; Affected:		W, STATUS
; Cycles:		3
; -------------------------------------------------------------------------------
callw macro addr, lit
    movlw	lit
    call	addr
    endm

; -------------------------------------------------------------------------------
; Syntax:		callf addr, freg
; -------------------------------------------------------------------------------
; Description:	Moves a file register value into W register and call the subroutine at addr.
; Arguments:	addr	the address of the soubroutine to call
;				freg	the file register to move in W
; Affected:		W, STATUS
; Cycles:		3
; -------------------------------------------------------------------------------
callf macro addr, freg
    movf	freg, W
    call	addr
    endm

; -------------------------------------------------------------------------------
; Syntax:		cmplf lit, freg
; -------------------------------------------------------------------------------
; Description:	Compares a literal value with a file register.
;				Executes freg - lit.
; Arguments:	lit		the literal value
;				freg	the file register
; Affected:		W, STATUS (freg>lit N=0 Z=0 C=1, freg=lit N=0 Z=1 C=1, freg<lit N=1 Z=0 C=0)
; Cycles:		2
; -------------------------------------------------------------------------------
cmplf macro lit, freg
    movlw   lit
    subwf   freg, W
    endm

; -------------------------------------------------------------------------------
; Syntax:		dec16f fregh, fregl
; -------------------------------------------------------------------------------
; Description:	Performs a 16 bit decrement involving two file registers.
; Arguments:	fregh	the high file register
;				fregl	the low file register
; Affected:		STATUS (C=0 if fregh overflow)
; Cycles:		3 or 5
; -------------------------------------------------------------------------------
dec16f macro fregh, fregl
	decf	fregl, F
	btfss	STATUS, C
	decf	fregh, F
	endm

; -------------------------------------------------------------------------------
; Syntax:		inc16f fregh, fregl
; -------------------------------------------------------------------------------
; Description:	Performs a 16 bit increment involving two file registers.
; Arguments:	fregh	the high file register
;				fregl	the low file register
; Affected:		STATUS (Z=1 C=1 if fregh overflow)
; Cycles:		1 or 2
; -------------------------------------------------------------------------------
inc16f macro fregh, fregl
	infsnz	fregl, F
	incf	fregh, F
	endm

; -------------------------------------------------------------------------------
; Syntax:		iorlf fregh, fregl
; -------------------------------------------------------------------------------
; Description:	Performs an inclusive OR between a literal value and a file register.
;				Stores the result in W or in a file register.
; Arguments:	lit		the literal value
;				freg	the file register
;				dest	F to store in freg, W to store in WREG
; Affected:		W, STATUS
; Cycles:		2
; -------------------------------------------------------------------------------
iorlf macro lit, freg, dest
    movlw   lit
    iorwf   freg, dest
    endm

; -------------------------------------------------------------------------------
; Syntax:		movlf lit, freg
; -------------------------------------------------------------------------------
; Description:	Moves a literal value to a file register.
; Arguments:	lit		the literal value
;				freg	the file register
;				dest	F to store in freg, W to store in WREG
; Affected:		W, STATUS
; Cycles:		2
; -------------------------------------------------------------------------------
movlf macro lit, freg
    movlw   lit
    movwf   freg
    endm

; -------------------------------------------------------------------------------
; Syntax:		mov16lf lit16, fregh, fregl
; -------------------------------------------------------------------------------
; Description:	Moves a 16 bits literal value to file registers.
; Arguments:	lit		the literal value
;				fregh	the high file register
;				fregl	the low file register
; Affected:		W, STATUS
; Cycles:		4
; -------------------------------------------------------------------------------
mov16lf macro lit16, fregh, fregl
    movlw   high lit16
    movwf   fregh
	movlw   low lit16
    movwf   fregl
    endm

; -------------------------------------------------------------------------------
; Syntax:		mov24lf lit24, fregu, fregh, fregl
; -------------------------------------------------------------------------------
; Description:	Moves a 24 bits literal value to a file registers.
; Arguments:	lit		the literal value
;				fregu	the upper file register
;				fregh	the high file register
;				fregl	the low file register
; Affected:		W, STATUS
; Cycles:		6
; -------------------------------------------------------------------------------
mov24lf macro lit24, fregu, fregh, fregl
    movlw   upper lit24
    movwf   fregu
	movlw   high lit24
    movwf   fregh
	movlw   low lit24
    movwf   fregl
    endm

; -------------------------------------------------------------------------------
; Syntax:		shftlf freg, pos
; -------------------------------------------------------------------------------
; Description:	Shifts to the left the content of a file register content by pos.
; Arguments:	freg	the file register to shift left
;				pos		the literal value indicating the number of bits to shift
; Affected:		W, STATUS
; Cycles:		2 if pos=1, 4 if pos=2, 5 if pos=3, 3 if pos=4, 4 if pos=5, 5 if pos=6, 3 if pos=7
; -------------------------------------------------------------------------------
shftlf macro freg, pos
    local n
    if pos < 4           
n = pos								 ; pos: 1 to 3
        while n > 0
            rlcf    freg, f
n--
        endw
        if pos == 1
            bcf     freg, 0
        else
            movlw   (0xFF << pos) & 0xFF
            andwf   freg, f
        endif
    else
        if pos < 6
            if pos == 4
                swapf   freg, f      ; pos == 4
                movlw   0xF0
                andwf   freg, f
            else
                swapf   freg, f      ; pos == 5
                rlcf    freg, f
                movlw   0xE0
                andwf   freg, f
            endif
        else
            if pos == 6
                swapf   freg, f      ; pos == 6
                rlcf    freg, f
                rlcf    freg, f
                movlw   0xC0
                andwf   freg, f
            else                    
                rrcf    freg, f      ; pos == 7
                clrf    freg
                rrcf    freg, f
            endif
        endif
    endif
    endm

; -------------------------------------------------------------------------------
; Syntax:		shftrf freg, pos
; -------------------------------------------------------------------------------
; Description:	Shifts to the right the content of a file register content by pos.
; Arguments:	freg	the file register to shift right
;				pos		the literal value indicating the number of bits to shift
; Affected:		W, STATUS
; Cycles:		2 if pos=1, 4 if pos=2, 5 if pos=3, 3 if pos=4, 4 if pos=5, 5 if pos=6, 3 if pos=7
; -------------------------------------------------------------------------------
shftrf macro freg, pos
    local n
    if pos < 4
n = pos								; pos: 1 to 3
        while n > 0
            rrcf    freg, f
n--
        endw
        if pos == 1
            bcf     freg, 7
        else
            movlw   (0xFF >> pos)
            andwf   freg, f
        endif
    else
        if pos < 6
            if pos == 4
                swapf   freg, f      ; pos == 4
                movlw   0x0F
                andwf   freg, f
            else
                swapf   freg, f      ; pos == 5
                rrcf    freg, f
                movlw   0x07
                andwf   freg, f
            endif
        else
            if pos == 6
                swapf   freg, f      ; pos == 6
                rrcf    freg, f
                rrcf    freg, f
                movlw   0x03
                andwf   freg, f
            else
                rlcf    freg, f      ; pos == 7
                clrf    freg
                rlcf    freg, f
            endif
        endif
    endif
    endm

; -------------------------------------------------------------------------------
; Syntax:		xorlf lit, freg, dest
; -------------------------------------------------------------------------------
; Description:	Performs an exclusive OR between a literal value and a file register.
;				Stores the result in W or in the file register.
; Arguments:	lit		the literal value
;				freg	the file register
;				dest	F to store in freg, W to store in WREG
; Affected:		W, STATUS
; Cycles:		2
; -------------------------------------------------------------------------------
xorlf macro lit, freg, dest
    movlw   lit
    xorwf   freg, dest
    endm
